home *** CD-ROM | disk | FTP | other *** search
- # ifndef lint
- static char RCSid[]="@(#)$Header: main.c,v 3.6 88/09/08 17:39:05 pb Exp $";
- # endif
-
- /***********************************************************************\
- * *
- * This program is responsible for reading a config file, *
- * scurrying about like a whirling dervish amongst numerous *
- * files, and outputing a load of names in some desired format. *
- * *
- * Copyright 1986, Piete Brooks, Julian Onions & Adrian Pell *
- * pb@cl.cam.ac.uk, jpo@hcig.nott.ac.uk, Adrian.R.Pell@reading.ac.uk *
- * *
- * This program may be copied as long as you don't remove this notice, *
- * try to make any money off of it, or pretend that you wrote it. *
- * *
- \***********************************************************************/
-
- #include "nrs.h"
- #ifdef USE_UNAME
- # include <sys/utsname.h>
- #endif USE_UNAME
-
- static_f void initderfil();
- static_f void init_files();
- static_f void m3process();
- static_f void m2process();
- static_f void domainprocess();
- static_f void init();
- static_f void tripcheck();
- static_f void checkatomicfiles();
- static_f void print_rec();
-
- void
- main(argc,argv)
- int argc;
- char **argv;
- {
- #ifdef USE_GETHOSTNAME
- char buffer[64];
-
- setlinebuf(stderr);
- #endif USE_GETHOSTNAME
- #ifdef USE_UNAME
- struct utsname utsname;
- #endif USE_UNAME
-
- invo_name = *argv;
- VOID fclose(stdin); /* we need every fd we can get! */
- if( argc > 1)
- config(++argv, argc - 1);
- else fatal0("I need a config file buddy!");
-
- #ifdef USE_GETHOSTNAME
- if( hostname == NULL)
- { VOID gethostname(buffer, sizeof(buffer) - 1);
- hostname = strdup(buffer);
- }
- #endif USE_GETHOSTNAME
-
- #ifdef USE_UNAME
- if( hostname == NULL)
- { uname (&utsname);
- hostname = utsname.nodename;
- }
- #endif USE_UNAME
-
- if (usederfil)
- initderfil(); /* read in the derived file */
- else
- init_files(); /* read in the files etc. */
- if( forwrev == REVERSE )
- m3process();
- else
- { m2process(); /* and off we go! */
- if (DOMfile && outputdomain)
- domainprocess(); /* process the domains */
- }
- exit(exit_rc(0));
- }
-
- static_f void
- init_files() /* read in files, building up indexs */
- {
- Table *tp;
-
- if( ! M2file )
- M2file = getfpath(MOD2);
- init(M2file, &Module2, FALSE); /* module 2 file */
- if( forwrev == REVERSE )
- {
- if( ! M3file )
- M3file = getfpath(MOD3);
- init(M3file, &Module3, FALSE);
- }
- if( ! M4file )
- M4file = getfpath(MOD4);
- init(M4file, &Module4, FALSE); /* module 4 file */
- /* now cycle though our list of atomic files got from config */
- for( tp = tablist; tp->T_name != 0; tp++)
- {
- init(tp->T_name, &tp->hdr, GETFNUMBER);
- max_fnumb = max(max_fnumb, tp->hdr.fnumber);
- }
- if (DOMfile) init(DOMfile, &Domains, FALSE);
- }
-
- static_f void
- initderfil()
- {
- FILE *fp;
- int ntriples, i;
-
- if (Derfile)
- fp = getfp(Derfile, "r"); /* get file pointer */
- else /* Try the two defaults */
- { Derfile = getfpath(DERFIL_D1);
- if (!(fp = getfp(Derfile, "Sr")))
- { Derfile = getfpath(DERFIL_D2);
- if (!(fp = getfp(Derfile, "Sr")))
- { Derfile = getfpath(DERFIL_D1);
- /* GENERATE ERROR */
- fp = getfp(Derfile, "r");
- }
- }
- }
- i = getint(fp, 5); /* how big is header? */
- ntriples = getint(fp, 5); /* should be one less */
- if (ntriples != i-1)
- fatal2("bad derived file -- %d triples instead of %d",
- ntriples, i-1);
- i = getint(fp, 5); /* offset to Module 2 */
- i = getint(fp, 5); /* offset to Module 3 */
- i = getint(fp, 5); /* offset to Module 4 */
- i = getint(fp, 5); /* offset to wildcard file */
- consistant(fp, Derfile); /* record version */
- skipnl(fp);
-
- for (i=1; i <= ntriples; i++)
- tripcheck(fp); /* record info about triples */
-
- checkatomicfiles(); /* do all required contexts exist? */
-
- /* now initialise details of all sub-files */
- M2file = Derfile;
- init(M2file, &Module2, FALSE);
- M3file = Derfile;
- init(M3file, &Module3, FALSE);
- M4file = Derfile;
- init(M4file, &Module4, FALSE);
-
- for (i=1; i <= ntriples; i++)
- init(Derfile, (Header *) 0, SEEKFNUMBER|GETFNUMBER);
-
- /* If anything given, use Derfil */
- if (DOMfile) DOMfile = Derfile;
-
- init(Derfile, &Domains, FALSE);
- }
-
- #ifndef findtriple
- Header *
- findtriple(fnumber)
- int fnumber;
- { Table *tp;
- for (tp = tablist; tp < &tablist[MAXTABLES]; tp++)
- if (tp->hdr.fnumber == fnumber) return &tp->hdr;
- return NULL;
- }
- #endif findtriple
-
- static_f void
- init(fname, mp, flag) /* open file - build seek index etc */
- char *fname;
- Header *mp;
- int flag;
- { static fnumber = 1;
- int nlines;
- int i;
- FILE *fp;
-
- fp = getfp(fname, "r");
- nlines = getint(fp, 5);
- if( flag & GETFNUMBER) /* this file has a file number */
- fnumber = getint(fp, 5);
- else fnumber++;
- consistant(fp, fname); /* check all files are from the
- same batch */
- skipnl(fp);
-
- if (flag & SEEKFNUMBER) {
- if ((mp = findtriple(fnumber)) == NULL) {
- for (i = 1; i < nlines; i++)
- skipnl(fp);
- return;
- }
- }
- mp->H_nlines = nlines;
- mp->fnumber = fnumber;
-
- /* malloc ourselves a seek table */
- mp->offset = (long *) calloc((unsigned) (mp->H_nlines+1),
- (unsigned) sizeof(off_t));
- if( mp->offset == NULL)
- fatal2("Out of memory (%d*%d bytes)", mp->H_nlines, sizeof(off_t));
- mp->offset[0] = mp->offset[1] = 0;
-
- /* now build the seek table */
- for( i = 2; i <= mp->H_nlines; i++)
- {
- mp->offset[i] = ftell(fp);
- skipnl(fp);
- }
- vprintf3(1, "read %4d lines of section %2d from %s\n",
- mp->H_nlines, mp->fnumber, fname);
- }
-
- static_f void
- tripcheck(fp)
- FILE *fp;
- {
- int context, subnet, direction, thisf;
-
- context = getint(fp, 5);
- subnet = getint(fp, 5);
- direction = getint(fp, 5);
- thisf = getint(fp, 5);
- if (trip2fnumb[context][subnet][direction])
- warn3(1, "Duplicate files %d and %d for context %d",
- thisf, trip2fnumb[context][subnet][direction],
- context);
- else trip2fnumb[context][subnet][direction] = thisf;
-
- fnumb = max(fnumb, thisf);
- if (thisf < MAX_FNUMB)
- { fnumb2trip[thisf].f_cont = context;
- fnumb2trip[thisf].f_subn = subnet;
- fnumb2trip[thisf].f_dirn = direction;
- fnumb2trip[thisf].f_tp = (struct Table *) 0;
- }
-
- skipnl(fp);
- }
-
- static_f void
- checkatomicfiles()
- {
- Table *tp;
-
- for (tp = tablist; tp < &tablist[MAXTABLES]; tp++) if (tp->T_name)
- { int file = 0;
- int i;
- for (i=0; i < MAX_FNUMB; i++)
- if (fnumb2trip[i].f_cont == tp->T_context &&
- fnumb2trip[i].f_subn == tp->T_network &&
- fnumb2trip[i].f_dirn == tp->T_direction)
- { if (file) warn2(1,
- "Duplicate files %d and %d", file, i);
- else file = i;
- }
-
- if (file && !fnumb2trip[file].f_tp)
- { tp->hdr.fnumber = file;
- tp->T_name = Derfile;
- cont_want[tp->T_context]++;
- if (file < MAX_FNUMB)
- fnumb2trip[file].f_tp = tp;
- max_fnumb = max(max_fnumb, file);
- }
- else
- { char *context = vlookup(tp->T_context, contexts);
- char *network = vlookup(tp->T_network, netnames);
- char *direction= vlookup(tp->T_direction, directions);
-
- warn3(1, (file) ?
- "Duplicate requests for %s-%s-%s" :
- "Couldn't find %s-%s-%s",
- context, network, direction);
- tp->T_name = NULL;
- }
- }
- }
-
- static_f void
- m2process() /* Your wish is my command */
- {
- Mod2 *m2p;
- Mod4 *m4p;
- Mod2 longname; /* These are NOT pointers, as getm2rec */
- Mod2 shortname; /* uses a built in static Mos2 */
- int i;
-
- for( i = 2; i <= Module2.H_nlines; i++) /* grap all relevant data */
- {
- if((m2p = getm2rec(i)) == NULL)
- { warn1(100, "problem on getm2rec rec %d", i);
- continue;
- }
- if( m2p->ls == SHORT )
- continue;
- longname = *m2p;
- if (longname.ls_disp)
- { if((m2p = getm2rec(longname.ls_disp)) == NULL)
- { warn1(100,
- "Can't find corresponding short entry for %s",
- longname.name);
- continue;
- }
- shortname = *m2p;
- m2p = &shortname;
- }
- else m2p = NULL;
-
- if((m4p = getm4rec(longname.index_disp)) == NULL)
- { warn1(100, "problem on getm4rec rec %d", i);
- continue;
- }
-
- /* if there is an m4 routine, call it. */
- if (! outputm4rec ||
- !(*outputm4rec)(m4p, m2p, &longname, (Mod3 *) 0))
- { int j;
- for( j = 0; j < m4p->nquads; j++)
- if (m4p->quads[j].fnumb <= max_fnumb)
- { Atomic *ap;
- if(( ap = getatrec(&(m4p->quads[j]),
- (m2p) ? m2p : &longname)) == NULL)
- continue;
- vprintf2(4, "[so `%s|%s']\n", longname.name,
- (m2p && m2p->name) ? m2p->name : "<unset>");
- (*outputformat)(&longname, m2p, ap, (Mod3 *) 0);
- }
- }
- }
- }
-
- static_f void
- m3process() /* Your wish is my command */
- {
- Mod2 *m2p;
- Mod3 *m3p;
- Mod2 longname;
- Mod2 shortname;
- int i;
-
- for( i = 2; i <= Module3.H_nlines; i++) /* grap all relevant data */
- {
- if((m3p = getm3rec(i)) == NULL)
- { warn1(100, "problem on getm3rec rec %d", i);
- continue;
- }
- /* Check we want this context ?? */
- if (!cont_want[m3p->m3_context]) continue;
- /* Check we want this context ?? */
- if((m2p = getm2rec(m3p->l_disp)) == NULL)
- { warn1(100, "problem on getm2rec %d", m3p->l_disp);
- continue;
- }
- longname = *m2p;
- if (longname.ls_disp) {
- if((m2p = getm2rec(longname.ls_disp)) == NULL)
- { warn1(100,
- "Can't find corresponding short entry for %s",
- longname.name);
- continue;
- }
- shortname = *m2p;
- m2p = &shortname;
- }
- else m2p = NULL;
-
- /* if there is an m4 routine, call it. */
- if (! outputm4rec ||
- !(*outputm4rec)(0, m2p, &longname, m3p))
- { int file = trip2fnumb[m3p->m3_context][m3p->m3_network][DIR_FORWARDS];
- if (file && fnumb2trip[file].f_tp)
- (*outputformat)(&longname, m2p, 0, m3p);
- }
- }
- }
-
- static_f void
- domainprocess()
- { int i, len;
- static Domain rec;
- FILE *fp = getfp(DOMfile, "r");
-
- for( i = 2; i <= Domains.H_nlines; i++) /* grap all relevant data */
- {
- VOID fseek(fp, Domains.offset[i++], 0);
- len = getint(fp, 2);
- getstr(fp, rec.name, 0, len);
- if( mixlow != MIXED )
- VOID lowerfy(rec.name); /* junk upper case! */
-
- VOID fseek(fp, Domains.offset[i++], 0);
- len = getint(fp, 2);
- getstr(fp, rec.gateway, 0, len);
- if( mixlow != MIXED )
- VOID lowerfy(rec.gateway); /* junk upper case! */
-
- VOID fseek(fp, Domains.offset[i], 0);
- rec.n_contexts = getint(fp, 2);
- for (len=0; len < rec.n_contexts; len++)
- rec.contexts[len] = getint(fp, 2);
- VOID (*outputdomain)(&rec);
- }
- }
-
- Mod2 *getm2rec( record) /* get a record from module2 file */
- int record;
- {
- FILE *fp = getfp(M2file, "r");
- static Mod2 rec;
-
- VOID fseek(fp, Module2.offset[record], 0);
- rec.index_disp = getint(fp, 4); /* index into module4 */
- rec.ls_disp = getint(fp, 4); /* index into mod2 */
- rec.ls = getint(fp, 1); /* long/short flag */
- rec.length = getint(fp, 2); /* number bytes in string */
- getstr(fp, rec.name, 9, rec.length); /* string */
- if( mixlow != MIXED )
- VOID lowerfy(rec.name); /* junk upper case! */
- return &rec;
- }
-
- Mod3 *getm3rec(record)
- int record;
- {
- FILE *fp = getfp(M3file, "r");
- static Mod3 rec;
- char *p, *q;
-
- VOID fseek(fp, Module3.offset[record], 0);
- rec.m3_context = getint(fp, 4);
- rec.m3_direction = DIR_REVERSE;
- rec.l_disp = getint(fp, 4);
- rec.m3_length = getint(fp, 2);
- getstr(fp, rec.m3_string, 10, rec.m3_length);
- p = rec.m3_string;
- if ((q = index(p, '.')) == NULL)
- return NULL;
- *q = '\0';
- if ((rec.m3_network = slookup(p, netabbrevs)) < 0)
- return NULL;
- *q = '.';
- /* ???if( mixlow != MIXED) lowerfy(rec.m3_string); DBM1??? */
- p = q + 1;
- if ((q = index(p, '.')) == NULL) {
- VOID strcpy(rec.m3_dte, p);
- VOID strcpy(rec.m3_ybts, nullstring);
- }
- else {
- *q = '\0';
- VOID strcpy(rec.m3_dte, p);
- VOID strcpy(rec.m3_ybts, q + 1);
- *q = '.';
- }
- return &rec;
- }
-
- Mod4 *getm4rec(record) /* get module 4 record */
- int record;
- {
- static Mod4 rec;
- int i;
- FILE *fp = getfp(M4file, "r");
-
- VOID fseek( fp, Module4.offset[record], 0);
- rec.nquads = getint(fp, 5); /* no of quads in record */
- if( rec.nquads > MAXQUADS)
- { warn2(100, "too many quads (%d) for rec %d",
- rec.nquads, record);
- }
-
- for(i = 0; i < rec.nquads; i++)
- { int q = (i > MAXQUADS) ? MAXQUADS : i;
- rec.quads[q].fnumb = getint(fp, 5); /* which atm file*/
- rec.quads[q].ngtwys= getint(fp, 5); /* no. gtwys ????*/
- rec.quads[q].disp = getint(fp, 5); /* disp in file */
- rec.quads[q].nlines= getint(fp, 5); /* no. lines */
- }
-
- if( rec.nquads > MAXQUADS) rec.nquads = MAXQUADS;
-
- return &rec;
- }
-
- Mod2 *findm2rec(name)
- char *name;
- {
- int low = 2;
- int high= Module2.H_nlines;
-
- while (low <= high)
- { int mid = (low+high)/2;
- int comp;
- Mod2 *rec = getm2rec(mid);
- if (!rec) return rec;
-
- comp = strcmp(name, rec->name);
- if (comp == 0) return rec;
- if (comp > 0) low = mid+1;
- else high = mid-1;
- }
- return (Mod2 *) 0;
- }
-
- /* Just loacte a record .. */
- FILE *
- locaterec(qp)
- Quad *qp;
- {
- FILE *fp;
- Table *tp;
- int file = qp->fnumb;
-
- if (file > fnumb) file = 3;
- if(file > max_fnumb ) /* not interested! */
- return (FILE *) 0;
- if((tp = gettab(file)) == NULL)
- {
- vprintf3(6, "can't find table %d(%d,%d)\n",
- qp->fnumb, qp->disp, qp->nlines);
- return (FILE *) 0;
- }
- /* Anything there ? */
- if (qp->disp == 0 || qp->nlines == 0) return (FILE *) 0;
-
- fp = getfp(tp->T_name,"r"); /* get an lru file desc. */
- VOID fseek(fp, tp->hdr.offset[qp->disp], 0);
-
- return fp;
- }
-
- Atomic *getatrec(qp, m2p) /* read record from atomic files */
- Quad *qp;
- Mod2 *m2p;
- {
- Table *tp;
- int i, len;
- char string[MAXNAMELEN];
- char tag[TAGSIZE];
- static Atomic ap;
- FILE *fp;
- int file = qp->fnumb;
-
- if (file > fnumb) file = 3;
-
- fp = locaterec(qp);
-
- if (!fp) return (Atomic *) 0;
-
- freeoff(&ap); /* junk previous data */
-
- tp = gettab(file);
- ap.context = tp->T_context;
- ap.network = tp->T_network;
-
- for( i = 1; i <= qp->nlines; i++)
- {
- getstr(fp, tag, 0, 4); /* the tag field */
- len = getint(fp, 5); /* length of next field */
- getstr(fp, string, 0, len); /* the ar/dte/ybts/di(de) */
- if( lexequ(tag, "dt", 2) )
- { if( ap.dte ) /* its a dte */
- { print_rec(qp, 0);
- warn0(100, "already got a dte");
- }
- ap.dte = strdup(string);
- }
- else if( lexequ(tag, "yb", 2) )
- { if( ap.ybts )
- { print_rec(qp, 0);
- warn0(100, "already got a yb");
- }
- ap.ybts = strdup(string);
- }
- else if( lexequ(tag, "ar", 2) )
- {
- if( ++ap.n_relays > MAXAR)
- { print_rec(qp, 0);
- warn0(100, "too many application relays");
- }
- /* ??? Should ARs be lowered ? Yes for mail, no x29 */
- else if( mixlow != MIXED)
- ap.ar[ap.n_relays-1] = strdup(lowerfy(string));
- else ap.ar[ap.n_relays-1] = strdup(string);
- }
- else if( lexequ(tag, "di", 2) | lexequ(tag, "de", 2) )
- {
- if( ++ap.n_descs > MAXDESC)
- { print_rec(qp, 0);
- warn0(100, "too many description lines");
- }
- else ap.desc[ap.n_descs-1] = strdup(string);
- }
- else
- { print_rec(qp, 0);
- vprintf3(0, "File %d/%d @ %d\n",
- qp->fnumb, file, qp->disp);
- warn2(100, "unknown line, '%s' '%s'", tag, string);
- }
- }
-
- if (! ap.dte || ! ap.ybts)
- {
- switch(ap.context)
- {
- case DESC: break; /* OK to have no DTE ... */
- case YBTS: /* OK to have no YBTS */
- case X29: if (ap.dte) break;
- default:
- { int level = (ap.dte) ? 2 : 0;
- char *net = vlookup(ap.network, netnames);
- char *con = vlookup(ap.context, contexts);
- print_rec(qp, level);
- vprintf3(level, "%-18s missing items for %s %s",
- m2p->name,
- (net) ? net : "<?>",
- (con) ? con : "<?>");
- if (ap.dte)
- vprintf1(level, ", dte %s", ap.dte);
- if (ap.ybts)
- vprintf1(level, ", ybts %s", ap.ybts);
- if (ap.n_relays)
- { vprintf0(level, ", relay:");
- for (i=0; i<ap.n_relays; i++)
- vprintf1(level, " '%s'", ap.ar[i]);
- }
- if (ap.n_descs)
- { vprintf0(level, ", desc:");
- for (i=0; i<ap.n_descs; i++)
- vprintf1(level, " '%s'", ap.desc[i]);
- }
- if (!ap.dte)
- { vprintf0(level, " -- entry ignored\n");
- return (Atomic *) 0;
- }
- vprintf0(level, "\n");
- }
- }
- if (!ap.ybts) ap.ybts = nullstring;
- if (!ap.dte ) ap.dte = nullstring;
- }
- return ≈
- }
-
- static_f void
- print_rec(qp, level)
- Quad *qp;
- int level;
- {
- int i, len;
- char string[MAXNAMELEN];
- char tag[TAGSIZE];
- FILE *fp = locaterec(qp);
-
- if (!fp)
- {
- vprintf0(level, "Couldn't find record\n");
- return;
- }
-
- for( i = 1; i <= qp->nlines; i++)
- { getstr(fp, tag, 0, 4); /* the tag field */
- len = getint(fp, 5); /* length of next field */
- getstr(fp, string, 0, len); /* the ar/dte/ybts/di(de) */
- vprintf3(level, "%-4s %2d '%s'\n", tag, len, string);
- }
- }
-